package com.gj.support;


import com.gj.config.BootstrapProperties;
import com.gj.executor.support.ResizableCapacityLinkedBlockingQueue;
import com.gj.model.ThreadPoolParameterInfo;
import com.gj.model.register.DynamicThreadPoolRegisterParameter;
import com.gj.model.register.DynamicThreadPoolRegisterWrapper;
import com.gj.remote.HttpAgent;
import com.gj.toolkit.JSONUtil;
import com.hippo4j.executor.DynamicThreadPoolExecutor;
import com.hippo4j.executor.DynamicThreadPoolWrapper;
import com.hippo4j.executor.manage.GlobalThreadPoolManage;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @方法描述：这个就是动态线程池对象的处理器，具体逻辑是这样的，大家在创建动态线程池对象的时候，可以看看DynamicThreadPoolConfig类中给出的几个现成例子 用户创建的动态线程池对象既可以以Executor的类型交给spring容器管理，也可以以ThreadPoolExecutor的类型交给spring容器管理，还可以直接以DynamicThreadPoolExecutor的类型交给spring的容器来管理
 * 当然，这些只是表面现象，使用不同的接口或者类型来接收动态线程池对象，实际上在内部，用户创建的就是一个DynamicThreadPoolExecutor对象，当然，这个DynamicThreadPoolExecutor
 * 对象也是继承了jdk的ThreadPoolExecutor对象。而当前的这个bean处理器，就是根据DynamicThreadPoolExecutor不同的返回类型
 * 得到真正创建的DynamicThreadPoolExecutor对象，然后把这个DynamicThreadPoolExecutor对象包装成DynamicThreadPoolWrapper对象，然后把这个对象保存到线程池动态管理器中
 * 并且把要注册对象信息交给DynamicThreadPoolConfigService对象，让DynamicThreadPoolConfigService对象去执行注册操作。
 * 简单概括一下，那就是DynamicThreadPoolPostProcessor处理器就是用来得到DynamicThreadPoolExecutor对象，然后把该对象保存到线程池动态管理器中，并且调用DynamicThreadPoolConfigService对象执行注册操作的。
 */
@Slf4j
@AllArgsConstructor
public final class DynamicThreadPoolPostProcessor implements BeanPostProcessor {

    //配置信息对象
    private final BootstrapProperties properties;

    //客户端代理对象
    private final HttpAgent httpAgent;

    //向服务端发起注册请求
    private final DynamicThreadPoolConfigService dynamicThreadPoolConfigService;


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //bean 是 DynamicThreadPoolExecutor 类型的，并且类上加了 @DynamicThreadPool 注解
        if (bean instanceof DynamicThreadPoolExecutor) {
            DynamicThreadPoolRegisterWrapper requestParam = new DynamicThreadPoolRegisterWrapper();
            requestParam.setTenantId(properties.getNamespace());
            requestParam.setItemId(properties.getItemId());
            DynamicThreadPoolRegisterParameter threadPoolRegisterParameter = new DynamicThreadPoolRegisterParameter();
            threadPoolRegisterParameter.setCorePoolSize(((DynamicThreadPoolExecutor) bean).getCorePoolSize());
            threadPoolRegisterParameter.setMaximumPoolSize(((DynamicThreadPoolExecutor) bean).getMaximumPoolSize());
            threadPoolRegisterParameter.setCapacity(((ResizableCapacityLinkedBlockingQueue<?>) ((DynamicThreadPoolExecutor) bean).getQueue()).getCapacity());
            threadPoolRegisterParameter.setAllowCoreThreadTimeOut(((DynamicThreadPoolExecutor) bean).allowsCoreThreadTimeOut());
            requestParam.setParameter(threadPoolRegisterParameter);

            dynamicThreadPoolConfigService.registerDynamicThreadPool(requestParam);
            GlobalThreadPoolManage.register(((DynamicThreadPoolExecutor) bean).getThreadPoolId(), JSONUtil.parseObject(JSONUtil.toJSONString(threadPoolRegisterParameter), ThreadPoolParameterInfo.class), (DynamicThreadPoolWrapper) bean);

            log.info(((DynamicThreadPoolExecutor) bean).getThreadPoolId() + " 注册成功了");
        }

        return bean;
    }
}
